package com.ajieee.merge.service.impl;

import com.ajieee.merge.entity.finance.dto.EtlManagerDTO;
import com.ajieee.merge.entity.finance.dto.EtlManagerRespDTO;
import com.ajieee.merge.entity.finance.po.EtfInfoPO;
import com.ajieee.merge.entity.finance.po.EtfQuotePO;
import com.ajieee.merge.entity.finance.po.EtlManagerPO;
import com.ajieee.merge.enums.finance.Exchange;
import com.ajieee.merge.mapper.EtfInfoMapper;
import com.ajieee.merge.mapper.EtfQuoteMapper;
import com.ajieee.merge.mapper.EtlManagerMapper;
import com.ajieee.merge.runner.finance.proxy.AkShareProxy;
import com.ajieee.merge.runner.finance.proxy.SseProxy;
import com.ajieee.merge.service.EtlManagerService;
import com.ajieee.merge.util.DBUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.client.RestClient;
import org.springframework.web.util.UriComponentsBuilder;

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ajieee
 * @date 2025-10-26
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EtlManagerServiceImpl implements EtlManagerService {

	private final EtlManagerMapper etlManagerMapper;

	private final AkShareProxy akShareProxy;

	private final EtfInfoMapper etfInfoMapper;

	private final EtfQuoteMapper etfQuoteMapper;

	private final SseProxy sseProxy;

	private final RestClient restClient;

	@Override
	public List<EtlManagerRespDTO> list(EtlManagerDTO dto) {
		LambdaQueryWrapper<EtlManagerPO> wrapper = Wrappers.<EtlManagerPO>lambdaQuery()
				.eq(dto.getDataDate() != null, EtlManagerPO::getDataDate, dto.getDataDate())
				.eq(dto.getResult() != null, EtlManagerPO::getResult, dto.getResult())
				.orderByDesc(EtlManagerPO::getDataDate)
				.orderByDesc(EtlManagerPO::getResult);
		List<EtlManagerPO> list = etlManagerMapper.selectList(wrapper);
		return list.stream().map(EtlManagerRespDTO::new).toList();
	}

	@SneakyThrows
	@Override
	public void syncSseEtfQuote() {
		Wrapper<EtfInfoPO> wrapper = Wrappers.<EtfInfoPO>lambdaQuery().eq(EtfInfoPO::getExchange, Exchange.SSE);
		List<String> fundCodes = etfInfoMapper.selectList(wrapper).stream().map(EtfInfoPO::getFundCode).toList();
		for (String fundCode : fundCodes) {
			List<EtfQuotePO> quotes = sseProxy.getEtfHistoryQuote(fundCode);
			if (!quotes.isEmpty()) {
				DBUtils.transaction(status -> {
					etfQuoteMapper.delete(Wrappers.<EtfQuotePO>lambdaUpdate().eq(EtfQuotePO::getFundCode, fundCode));
					etfQuoteMapper.insert(quotes);
				});
			}
			log.info("同步{}的行情数据完成", fundCode);
			Thread.sleep(500);
		}

		log.info("同步所有SSE的行情数据完成");
	}

	@SneakyThrows
	@Override
	public void syncSzseEtfQuote() {
		Wrapper<EtfInfoPO> wrapper = Wrappers.<EtfInfoPO>lambdaQuery().eq(EtfInfoPO::getExchange, Exchange.SZSE);
		List<String> fundCodes = etfInfoMapper.selectList(wrapper).stream().map(EtfInfoPO::getFundCode).toList();
		for (String fundCode : fundCodes) {
			String uriString = UriComponentsBuilder.fromUriString("https://stock.xueqiu.com/v5/stock/chart/kline.json")
					.queryParam("symbol", "SZ" + fundCode)
					.queryParam("period", "day")
					.queryParam("begin", System.currentTimeMillis())
					.queryParam("type", "normal")
					.queryParam("count", -99999)
					.queryParam("indicator", "kline,pe,pb,ps,pcf,market_capital,agt,ggt,balance")
					.build().encode().toUriString();
			JsonNode root = restClient.get()
					.uri(uriString)
					.header("cookie", "cookiesu=421754808175810; device_id=5fddef2b1a4e3f5b5fce2cf0b1d2f718; s=bz113ofog7; remember=1; xq_a_token=0706b2e60c8be0399f539834c6fcc50a3b23d15b; xqat=0706b2e60c8be0399f539834c6fcc50a3b23d15b; xq_id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOjkxMzE4MDkyNjYsImlzcyI6InVjIiwiZXhwIjoxNzYzNTU0NDc0LCJjdG0iOjE3NjA5NjI0NzQwNTQsImNpZCI6ImQ5ZDBuNEFadXAifQ.gUFz_Ge2m1JqMXsTqPc5xajzGq6GbaUEK-ganK-OZ2FHpxlV4_n6mGM5-BhqC3YuyD0PGp2N-ONLC4Erd1Z1yHSj-4g7a6UrOLm02t3IKQp04pNEb7wGxqODURBMTlKlBngrP_i8rG3BWoUsIEUOIfiJbV3e3tHO0Z6Tgj4ZqCRdcwAvBlv23QYPnnVWJ3r9AaxpRvyVxGA1F2FilL3xXtnrF3usitq8c8UFlvNzZz3e1iNCRAGzwPEJh8HyjDzrJWrXdu1OgkK6-3839gstyf55zh3VnFZEl4jWGdPst0pMuXZVo3emKZ4BA8XNUQS4CIuASrIBorvDamQ-eGU1UQ; xq_r_token=e59adce734d943c250d221e26d76e2c8dd37dfe2; xq_is_login=1; u=9131809266; bid=d212225b928ea149a36bdc7e3165ec0d_mgz4g95f; Hm_lvt_1db88642e346389874251b5a1eded6e3=1760962438,1761046085,1761912761; HMACCOUNT=D101F02633906DCF; is_overseas=0; Hm_lpvt_1db88642e346389874251b5a1eded6e3=1761912774; ssxmod_itna=1-QuitAIq0rx8DODhx_EA3NG7GkDmxjx40dGMD3dq7UtGcD8gx0phBEIt2E6XfEv6=NW7inv4gD0ymq_DA5DnCx7YDtoRaqPDGoyv=8NjC_RsPImM0GNYaebEFKYVfDE9S3TTXZxlfONO=MBSQDU4GnD06xzAdrDYYfDBYD74G_DDeDih3Dj4GmDGYN1eDFUjui5ZRY=xDwDB=DmqG2QgbDm4DfDDLd5DQ6UCRYDDtDAMa_HPDADA3=c4Dln_86zBD5sDGWUeWqwcmO=zDiv7_dx0UWDBLqFN7_Oy16QPWR=Hkm_lcHxBQD7uFz4ru3K84a_Rr8TeNAxYEh_Gd4relO4q74HAx8r==GhsBqNiYT7wCx4ai=NA4QSQq3__7OgidvEwQfxDbeMusxlbqjG_ixQnhNADtCQk7DYhohrdshEwWe1W5l0Qprdzhr5ADPYexgDQb_PiDD; ssxmod_itna2=1-QuitAIq0rx8DODhx_EA3NG7GkDmxjx40dGMD3dq7UtGcD8gx0phBEIt2E6XfEv6=NW7inv4_DDpAePhD7poqIBQxD/zDcg5D0QESFv=C/Bw_fT5DZuhXt1h/Tk7hZ4/695Rv/B09fyTLh4/MxjzADvKG=79MqS/df20b2VCWA0RkUKI8u9Bdr9DTvekA6=D63x2S=KCfGxlk_qYajeSeInm=2Q6x3087wVWYdGhnUnKAnMCxgljTjxRk_EGxSlzG8PTCGLFax0_Kbfg8yV9iQ7Ia3YNBW0ulh6KIjRsL_2WvyEI6T1ktaeZIyap=CQAgp=gIKQj0ZQ5PUyGtSrGVmKHC3sBvOg_qzIapXL72TPUD/0LEifBvahQe_Rc13HliUgYtFtd_PPejEldVCu6p3yQEl72DEbymIqe50YfKB50GPO2IzxRXpARh=nEtU=hhhd6BqXlIeBmdmA0/DGg3TbYPBAFxr1BYzWN7=KnBPeouUPKuzK01a8toUaYyQbXncc_P2ePuDUsPjniBcOohzKAGQUrDyliXeoH0NVlK7zoBK0K7=wEiib=UFtnZNjQ07VugPKVGA3LLMzK2DUxsn/RjGb34hU5KSoiTQdQvDUSBIElhBQ5D19hqHAMLbO5nQDr7hPmq0Cte=6nDzuQ=vizAeoeBy2WDnjhO6xPAwuj5gvYSLPXypm3ZUNrBxeh60DPhKY59hzB53G6Bq44elDd0o0DPD")
					.header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0")
					.retrieve()
					.body(JsonNode.class);
			Assert.notNull(root, "没有数据");

			JsonNode data = root.get("data").get("item");
			List<EtfQuotePO> quotes = new ArrayList<>(data.size());
			for (JsonNode node : data) {
				EtfQuotePO po = new EtfQuotePO();
				LocalDate dataDate = Instant.ofEpochMilli(node.get(0).asLong())
						.atZone(ZoneId.systemDefault()).toLocalDate();
				po.setDataDate(dataDate);
				po.setFundCode(fundCode);
				po.setOpen(node.get(2).asDouble());
				po.setHigh(node.get(3).asDouble());
				po.setLow(node.get(4).asDouble());
				po.setClose(node.get(5).asDouble());
				po.setChange(node.get(6).asDouble());
				po.setChangeRatio(node.get(7).asDouble());
				po.setVolume(node.get(1).asDouble());
				po.setAmount(node.get(9).asDouble());
				quotes.add(po);
			}

			if (!quotes.isEmpty()) {
				DBUtils.transaction(transactionStatus -> {
					etfQuoteMapper.delete(Wrappers.<EtfQuotePO>lambdaUpdate().eq(EtfQuotePO::getFundCode, fundCode));
					etfQuoteMapper.insert(quotes);
				});
			}
			log.info("同步{}的行情数据完成", fundCode);
			Thread.sleep(500 + (int) (Math.random() * 1000));
		}

		log.info("同步所有SZSE的行情数据完成");
	}
}
